﻿using Coomtools.commclass;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.ComponentModel;

namespace Coomtools.weightclasses
{

   
    public class Aclas51 : Myweightbase,IweightInteface
    {
        //*********************************导入dll声明***********************************************
        #region 导入dll声明
        const string LibraryName = "ExtrDlls/PBUSDRV.DLL";
        //const string LibraryName = "PBUSDRV.DLL";
        //        传送Hotkey函数
        //Function PBusTransferHotkey(HotkeyTable:PHotkeyTable; //热键表
        //        TableIndex:Integer	//热键表号,共有两张热键表,分别为0和1
        //                            ):Integer;far; external 'PbusDrv.dll';

        [DllImport(LibraryName)]
        public static extern int PBusTransferHotkey(int[] Hotkey, int TableIndex);

        /// <summary>
        /// com口ip口连接函数
        /// </summary>

        [DllImport(LibraryName)]
        public static extern int PBusConnect(string RefLFZKFileName, string RefCFGFileName, int SerialNO,

                                         string CommName, int BaudRate);
        /// <summary>
        ///  ip口连接函数 
        /// </summary>
        /// <param name="RefLFZKFileName"></param>
        /// <param name="RefCFGFileName"></param>
        /// <param name="IPAddr"></param>
        /// <returns></returns>
        //[DllImport("PBUSDRV.DLL", EntryPoint = "PBusConnectEx", SetLastError = true,
        //        CharSet = CharSet.Auto, ExactSpelling = false,
        //        CallingConvention = CallingConvention.StdCall)]
        [DllImport(LibraryName)]
        public static extern int PBusConnectEx(string RefLFZKFileName, string RefCFGFileName, string IPAddr);

        /// <summary>
        /// com口断开函数
        /// </summary>
        /// <param name="RefLFZKFileName"></param>
        /// <param name="RefCFGFileName"></param>
        /// <param name="IPAddr"></param>
        /// <returns></returns>

        [DllImport(LibraryName)]
        public static extern int PBusDisConnect(string SerialNO);
        /// <summary>
        /// ip口断开函数
        /// </summary>
        /// <param name="IPadress"></param>
        /// <returns></returns>
        [DllImport(LibraryName)]
        public static extern int PBusDisConnectEx(string IPadress);
        /// <summary>
        /// PLU簇传输函数
        /// </summary>
        /// <param name="PLUCluster">4个PLU的数组</param>
        /// <returns></returns>
        [DllImport(LibraryName)]
        public static extern int PBusTransferPLUCluster(TranPLU[] PLUCluster);
        //******************PLU结构体声明**********************************************
        /// <summary>
        /// 51模式 对称传称用的 PLU结构体
        /// </summary>
        public struct TranPLU
        {

            public string PLUName;//品名,36个字符
            public Int32 LFCode;//生鲜码,1-999999,唯一识别每一种生鲜商品
            public string Code;//货号，10位数字,用来组成条码
            public Int32 BarCode;//条码类型,0-99
            public Int32 UnitPrice;//单价,无小数模式,0-9999999
            public Int32 WeightUnit;//称重单位 0-12
            public Int32 Deptment;//部门,2位数字,用来组成条码
            public double Tare;//皮重,逻辑换算后应在15Kg内
            public Int32 ShlefTime;//保存期,0-365
            public Int32 PackageType;//包装类型,0:普通/限重模式,1:定重包装,2:定价包装,3:条码打印机模式
            public double PackageWeight; //包装重量/限重重量,逻辑换算后应在15Kg内
            public Int32 Tolerance;//包装误差,0-20
            public byte Message1;//信息1,0-197
            public byte Reserved;//保留
            public int Reserved1;//保留
            public byte Message2;//信息2,0-197
            public byte Reserved2;//保留
            public byte MultiLabel;//多标签,0-255,8个Bit位分别对应A0-D1
            public byte Rebate;//折扣,0-99
            //int Account;//入账,保留

        }



        #endregion

       
        //****************************51模式内部数据结构声明***********************************************
        public TranPLU[] PLUCluster = new TranPLU[4];//一个PLU簇包含4条PLU
      
        public int[] HotkeyTable = new int[112];//每一个数组元素为一条PLU的生鲜码,112个元素对应112条PLU
       
      /// <summary>
      /// 接受界面传来的plu集合
      /// </summary>
        private BindingList<Uipluitem> InuipluList =new BindingList<Uipluitem>();


        //****************************功能实现正文***********************************************

        #region 普通常用方法
        /// <summary>
        ///在字典里通过value找key
        /// </summary>
        /// <param name="D_WeightUnitflag">字典</param>
        /// <param name="value">value</param>
        /// <returns>key值 或 null</returns>
        string GetDictionaryKey(Dictionary<string, string> D_WeightUnitflag, string value)
        {

            foreach (var key in D_WeightUnitflag.Keys)
            {
                if (D_WeightUnitflag[key].Equals(value))
                {
                    return key;
                }
            }
            return null;


        }
        #endregion


        #region 1.初始化阶段

        /// <summary>
        /// 有参 构造函数用于传输plu界面传输plu用
        /// </summary>
        /// </summary>
        /// <param name="InUIpluList">界面显示的plu信息的集合</param>
        public Aclas51(BindingList<Uipluitem> InUIpluList)
        {
            InuipluList=InUIpluList;

            InitThisClass();

        }
     /// <summary>
     /// 无参构造用于读取plu源文件文件初始化本类
     /// </summary>
        public Aclas51()
        {

            InitThisClass();

        }

            /// <summary>
            /// 初始化本类 的方法 对各种解析定义函数
            /// </summary>
            public void InitThisClass()
        { 
            //  *********能解析的单位定义*********

            D_WeightUnitflag.Add("4", "公斤");
            D_WeightUnitflag.Add("10", "pcs(kg)");
            D_WeightUnitflag.Add("7", "500g");
            D_WeightUnitflag.Add("1", "克");
            D_WeightUnitflag.Add("2", "10g");
            D_WeightUnitflag.Add("3", "100g");
            D_WeightUnitflag.Add("9", "pcs(g)");
            D_WeightUnitflag.Add("8", "600g");
            //  *********能解析的条码类型定义*********

        }
        #endregion

    
        #region 2.阶段资源文件并解析出界面可显示的元素 因资源文件中 重量单位，条码类型等用数字表示不直观
  /// <summary>
        /// 检查是否是文本文件
        /// </summary>
        /// <param name="readfilepath"></param>
        /// <returns></returns>
        public bool CheckIsNeedFile(string readfilepath)
        {
         return  FileoperHelper.CheckIsTextFile(readfilepath);
        }

      /// <summary>
        /// 匹配已知道的本类中 数字代表的重量单位
        /// </summary>
        /// <param name="weightunitflag"> 数字代表的重量单位</param>
        /// <returns>汉字重量单位</returns>的方法
        public string findMyWeightUnitFlag(string weightunitflag)
        {
            foreach (var item in D_WeightUnitflag.Keys)
            {
                if (item == weightunitflag)
                    return D_WeightUnitflag[item];

            }

            return weightunitflag;

        }

        /// <summary>
        /// 读取51模式支持的源文件并解析
        /// </summary>
        /// <param name="readfilepath">源文件路径</param>
        /// <returns>返回 BindingList < Uipluitem >集合 </returns>
        public dynamic ReadPLuResourseFile(string readfilepath)
        {
           

             //生成界面控件需要的PLU list集合
              BindingList < Uipluitem > RPLUList = new BindingList<Uipluitem>();
          
            Encoding encoding = Encoding.Default;
            StreamReader streamreader = new StreamReader(readfilepath, encoding);
            try
            {
                 int count=1;
                //StreamReader streamreader = new StreamReader(readfilepath);
                while (streamreader.Peek() != -1)
                {
                  
                    string sreadline = streamreader.ReadLine();
                    string[] s = sreadline.Split('\t');
                    if (s.Length > 6)
                    {
                        //***************** 解析文件数据到界面 显示用***************
                       
                        Uipluitem rp = new Uipluitem();
                        rp.serialnumber = count.ToString();
                        rp.pluname = s[1];
                        rp.lfcode= s[2];
                        rp.PLUcode = s[3];
                        //条码类型2 为13位金额码 7为重量码 其他参考手册
                        rp.barcodeclass = s[4];
                        rp.price = (Convert.ToDouble(s[5]) / 100).ToString("0.00");
                        rp.unit = s[6];
                        rp.unitcode = rp.unit;
                        //？？？？？？后期 改？？？？？？？？？ 当条码格式为0表示为定义 将他强制转换为2目前
                        //有些称plu文件中并没有条码类型设置，就将其统一调整为 2 13位金额
                        if (rp.barcodeclass=="未设置"||rp.barcodeclass=="0")
                        {
                            rp.barcodeclassCode = "2";
                            //界面绑定的barcodeclass 也同步一下
                            rp.barcodeclass = rp.barcodeclassCode;
                        }
                        else
                        rp.barcodeclassCode = rp.barcodeclass;

                        //****************解析单位 ************* 

                        rp.unit = findMyWeightUnitFlag(rp.unit);

                        //*****************将热键字符去掉前导0 并保留3位热键***********
                        Regex reg = new Regex(@"^0+");
                        rp.HotKey = rp.PLUcode;
                        string hotkey1 = rp.HotKey;
                        if (hotkey1.Length >= 3)
                        {
                            hotkey1 = rp.HotKey.Substring(rp.HotKey.Length - 3, 3);
                            rp.HotKey = reg.Replace(hotkey1, "");
                        }
                        else
                        {
                            rp.HotKey = reg.Replace(hotkey1, "");
                        }

                        rp.WeightFlage = s[7];
                        RPLUList.Add(rp);
                        count++;
                    }


                }
                streamreader.Close();
            }
            catch (Exception e)
            {
                streamreader.Close();
                throw e;

            }


            return RPLUList;
        }
        #endregion

        //*******因为顶尖51模式是内存数据传输plu数据可不将plu写入到文本文件中********
        #region 3.传输前准备阶段 将界面控件显示的plu内容转换为厂家动态库可传输的plu集合
        /// <summary>
        /// 将界面的plulist转换为51模式能够传输的plulist列表
        /// </summary>
        /// <param name="InUIpluList"></param>
        /// <returns></returns>

        public List<TranPLU> GetTranfPLuList(BindingList<Uipluitem> InUIpluList)
        {
            List<TranPLU> TranpluList = new List<TranPLU>();


            foreach (var item in InUIpluList)
            {
                TranPLU Tplu = new TranPLU();
                Tplu.PLUName = item.pluname;
                Tplu.LFCode = Convert.ToInt32(item.lfcode);
                Tplu.Code = item.PLUcode;
                //？？？？？？后期 改成自定义？？？？？？？？？ 当条码格式为0表示为定义 目前将他强制转换为2
                if (item.barcodeclass == "未设置"||item.barcodeclass=="0")
                {
                    Tplu.BarCode = 2;
                }
                
                else
                Tplu.BarCode = Convert.ToInt32(item.barcodeclass);
               //将汉字单位重新解析为数字
                string getweightunit= GetDictionaryKey(D_WeightUnitflag,item.unit);
               
                if (getweightunit !=null)
               
                    Tplu.WeightUnit = Convert.ToInt32(getweightunit);
                   
                else 
                       //没找到单位对照表的按4 的方式公斤传
                        Tplu.WeightUnit = 4;


               
                Tplu.UnitPrice = Convert.ToInt32(Convert.ToDouble(item.price) * 100) ;
                Tplu.Deptment = Convert.ToInt32(item.WeightFlage);
                TranpluList.Add(Tplu);
            }
                return TranpluList;
        }



        #endregion


        //////////////*********************开始传输阶段******************************

        #region 4.开始传输阶段
        /// <summary>
        /// 51模式连接电子称
        /// </summary>
        /// <param name="IPAdress">电子称IP</param>
        /// <returns>成功返回 true</returns>
        public bool Link_EWeightOK(string IPAdress,string port)
        {

            try
            {
               int result = PBusConnectEx("lfzk.dat", "system.cfg", IPAdress.Trim());
             if (result < 0) 
                return false; 
            else
                return true; 
            }
            catch (Exception ex)
            {
                return false;
                throw ex;
            }
           
            
           
        }

       /// <summary>
       /// 开始传输plu
       /// </summary>
       /// <param name="IPAdress">称ip</param>
       /// <param name="port">称端口</param>
       /// <returns>传输的plu个数，不成功返回-1</returns>
        public int StartTranfPLU(string IPAdress, string port)
        {
            int SendOkcount = 0;
            List<TranPLU> UseTranPLUList = new List<TranPLU>();
            UseTranPLUList = GetTranfPLuList(InuipluList);

            try
            {
                for (int i = 0; i < UseTranPLUList.Count; i++)
                {
                    PLUCluster[0] = UseTranPLUList[i];
                    PBusTransferPLUCluster(PLUCluster);
                    SendOkcount++;
                }
     
                PBusDisConnectEx(IPAdress);
                return SendOkcount;

            }


            catch (Exception)
            {
                PBusDisConnectEx(IPAdress);
                return -1;
                throw;
            }





        }

        /// <summary>
        /// 传送一个热键
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool TranOneHotKey( Uipluitem item)
        { 
            int TableIndex=0;
            int hotkeyvalue=1;
           int hotkeypassion;
            int plucode;
            try
            {
          hotkeyvalue = Convert.ToInt32(item.HotKey);
             plucode = Convert.ToInt32(item.PLUcode);
            }
            catch (Exception)
            {
                return false;   
                
            }
           
            
           
           
            if (hotkeyvalue > 112)
            {
                TableIndex = 1;
                hotkeypassion = hotkeyvalue - 113;
            }
            else
            {
                hotkeypassion = hotkeyvalue - 1;
            }
            if (hotkeypassion <= 0 && hotkeypassion > 224)
            {
             
                return  false;

            }
            try
            {

            }
            catch (Exception)
            {

                throw;
            }
           
            
            HotkeyTable[hotkeypassion] = plucode;
            int succs = PBusTransferHotkey(HotkeyTable, TableIndex);
            if (succs<0)
            {
           
                return false;
            }
         
            return true;

        }
        /// <summary>
        /// 传送热键的方法 由于SDK提供的 传热键只能对84热键老称适用，即使改热键表为112也只能正确传前84个热键后边对不上
        /// </summary>
        /// <param name="IPAdress"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public int StartTranHotKey(string IPAdress, string port)
        {
           
            int SendOkcount = 0;
            try
            {
                foreach (var item in InuipluList)
                {
                    if (TranOneHotKey(item))
                    {
                        
                        
                        
                        SendOkcount++;
                    }

                }

                PBusDisConnectEx(IPAdress);
                return SendOkcount;
            }
            catch (Exception)
            {
                PBusDisConnectEx(IPAdress);
                return -1;
                throw;
            }





        }

        public bool Close_EWeightConnect(string IPAdress, string port)
        {
            try
            {
                PBusDisConnectEx(IPAdress);
                return true;
            }
            catch (Exception ex)
            {
                return false;
                throw ex;

            }
        }

        #endregion






    }
}
